package xfuzzy.xfghl.selection;

import java.util.ArrayList;
import java.util.List;

import xfuzzy.xfghl.codification.DoubleChromosome;
import xfuzzy.xfghl.population.Population;

/**
 * Clase que realiza la seleccion de individuos para el cruce y la mutacion usando un torneo
 * @author Alberto David Fernandez Fernandez
 * */

public class SelectionTournament extends Selection {
	
	/**
	 * Numero de individuos en el torneo
	 * */
	private int sizeTournament;
	
	/**
	 * Constructor de la clase
	 * @param numIndividuos Numero de individuos en el torneo
	 * @param seed Semilla del generador de numeros aleatorios
	 * */
	
	public SelectionTournament(int numIndividuos, long seed)  {
		
		super(seed);
		this.sizeTournament = numIndividuos;
	}
	
	public int getNumIndividuos() {
		return sizeTournament;
	}

	public void setSizeTournament(int sizeTournament) {
		this.sizeTournament = sizeTournament;
	}

	/**
	 * Metodo que selecciona dos individuos de la poblacion
	 * @param poblacion Poblacion de individuos
	 * @return Lista de individuos seleccionados
	 * */
	
	@Override
	public List<DoubleChromosome> seleccionar(Population poblacion) {
		
		DoubleChromosome seleccionado1 = null, seleccionado2 = null;
		List<DoubleChromosome> seleccionados = new ArrayList<DoubleChromosome>();
		seleccionado1 = this.realizarTorneo(poblacion);
		seleccionados.add(seleccionado1);
		
		seleccionado2 = this.realizarTorneo(poblacion);
		while (seleccionado1.getIdentification().compareTo(seleccionado2.getIdentification()) == 0)
			seleccionado2 = this.realizarTorneo(poblacion);
		
		seleccionados.add(seleccionado2);
		return seleccionados;
	}
	
	/**
	 * Metodo que selecciona un individuo a traves de un torneo
	 * @param poblacion Poblacion de individuos
	 * @return DoubleChromosome Individuo vencedor del torneo
	 * */
	
	private DoubleChromosome realizarTorneo(Population poblacion)  {
		
		List<DoubleChromosome> seleccionados = new ArrayList<DoubleChromosome>();
		DoubleChromosome seleccionado = null;
		DoubleChromosome individuo = null;
		int indice = -1;
		for (int iteracion = 0; iteracion < this.sizeTournament; iteracion++)  {
			 indice = this.random.nextInt(poblacion.getPoblacionSize());
			 individuo = poblacion.getIndividuo(indice);
			 while (seleccionados.contains(individuo))  {
				 indice = this.random.nextInt(poblacion.getPoblacionSize());
				 individuo = poblacion.getIndividuo(indice);
			 }
			 seleccionados.add(individuo);
		}
		seleccionado = seleccionados.get(0);
		for (int iteracion = 1; iteracion < this.sizeTournament; iteracion++)
			 if (seleccionados.get(iteracion).getFitness() < seleccionado.getFitness())
				 seleccionado = seleccionados.get(iteracion);
		return seleccionado;
	}
}
